#define OSPROC_CPP
#include <structure.h>
#include <OSProc.h>
#include <BasicMatic.h>
#include <compile.h>

//#include "IFD.h"

//MACRO
#define HIGH(n)				(0xFFFFFFFF << n)
#define LOW(n)				(0xFFFFFFFF >> n)
#define HWREG(x)                        (*((volatile unsigned int *)(x)))

#define UI_ADDRESS			(0xD0000000)
#define NOW				(((_tcb*)(run->content))->pPro)
#define NOWT				((_tcb*)(run->content))
#define NOWP				(((_tcb*)(run->content))->init_argv[0])
#define FAULT_MASK (1039)
#define WRITE_OR_READ (1 << 11)

#define _KHEAPAPPLY(x)			(Kmalloc((_mch*)&kmemory,x))
#define _KHEAPRELEA(x)			(Kfree((_mch*)&kmemory,(_ptlong*)(x)))

#define	__DSB()		__asm__ __volatile__("DSB;")
#define	__DMB()		__asm__ __volatile__("DMB;")
#define	__ISB()		__asm__ __volatile__("ISB;")

#define IS_PUB_MEM(x)		((x >= PUB_MEM_START) && (x <= PUB_MEM_END))
#define IS_KERNEL_MEM(x)	((x >= KERNEL_START) && (x <= KERNEL_END))	

#define VaToPa(x)		(x /*- 0x70000000*/)
#define PaToVa(x)		(x /*+ 0x70000000*/)



#define NOW	(((_tcb*)(run->content))->pPro)

//EXTERNAL FUNCTION
extern void MMUFLTInit(unsigned int FirTableBase);
extern void MMUSLTInit(unsigned int FirTableBase,unsigned int VirAddr,unsigned int SecTableBase);//Initalize 1MB -- 1KB things
extern void MMURemap4KB(unsigned int FirTabBase,unsigned int VirAddr,unsigned int PhyAddr);

extern void StopTimer();
extern void StartTimer();
extern int VFSWrite4KB(_pcb* pro,unsigned int vaddr,unsigned int paddr);
extern int VFSRead4KB(_pcb* pro,unsigned int vaddr,unsigned int paddr);
extern void VFSOpenExcuteFile(char* filename,unsigned long strlen,_pcb* pro);
extern int ThreadEntrySet(_stk* stack,unsigned int* entry,unsigned long* argv,unsigned long args);
extern void SetStackPoint(unsigned int addr);
extern void GeneralEntry(unsigned long* fun,unsigned long* argv,unsigned long args);
extern void KillItself();
extern unsigned int* MMUVirAddrTo(unsigned int FirTabBase,unsigned int VirAddr);

extern volatile _pcb VFS;
extern volatile _pcb* IFD[16];
extern const char SWAP_PATH[];


//GLOBAL VAR
volatile unsigned int old;
volatile unsigned int young;

//INTERNAL FUNCTION
unsigned int SearchSparePSpace(); //untested
unsigned int GetPMOwner(unsigned int pAddr,unsigned int* vAddr); // untested
void MarkSpareSpace(unsigned int pID,unsigned int vAddr,unsigned int pAddr);//untested

static unsigned int proNumber = 2;
static unsigned int thrNumber;
void ThreadInitialize(_tcb* tHandle,_pcb* pHandle,unsigned int* entry,unsigned long* argv,unsigned long args);
_pcb* FindProcess(unsigned int pID);
static void TaskStackSave(stk_item* stack,stk_item* stackStore);
static void TaskStackOut(stk_item* stack,stk_item* stackCover);



extern volatile _mch kmemory;

volatile ring* run;
volatile ring* sleep;



  //Thread
  inline int KernelSchedule(_ptlong mark)
  {
	
  }

  inline _tcb* BuildThread(_pcb* pro,_ptlong Function)
  {

  }
  inline _tcb* ArgvThread(_tcb* thr,_ptlong* argvs,_ptlong args)
  {

  }
  inline _tcb* RunThread(_tcb* thr)
  {
	
  }

  inline _tcb* KillThread(_tcb* thr)
  {

  }
  //Process



  inline int KillProcess(_pcb* pro)
  {

  }


static void _ProcessTerminate(_pcb* pro)
{
  _KHEAPRELEA(NOW->flPage);
  DeleteAllMessage(NOW->msgbox);
  DeleteAllHookToMessage(NOW->hooks);
  _KHEAPRELEA(pro);	
}

static void _ThreadTerminate(_tcb* tthread)
{
//  if(tthread->init_argv != NULL)
//    _KHEAPRELEA(tthread->init_argv);
  _KHEAPRELEA(tthread->stackPoint);
  if((tthread->pPro)->mthread == tthread)
    _ProcessTerminate(tthread->pPro);
  ReliefSList(tthread->streams);
  _KHEAPRELEA(tthread);
}


static void ProcInitalize(_pcb* pHandle) //unfinished
{

}

static void HookThreadInitialize(_tcb* tHandle,_pcb* pHandle,unsigned int* entry,unsigned long* argv,unsigned long args)
{

}

static void NORMAL_ThreadTurning()//untested
{
	
}

static void MUTEX_ThreadTurning()//untested
{
  __asm__ __volatile__
    (	
     "MOV r0, %0;"
     "SVC 0x00;"
     :
     :"r"(SCHEDULE_MUTEX)
     :
	);
	
}
static void TaskStackSave(stk_item* stack,stk_item* stackStore)
{
  unsigned char i;
  for(i = 0 ; i < sizeof(_stk)/sizeof(stk_item) - 2 ; i++)
    {
      *stackStore++ = *stack++; //PUSH IN
    }
}

static void TaskStackOut(stk_item* stack,stk_item* stackCover)
{
  unsigned char i;
  for(i = 0 ; i < sizeof(_stk)/sizeof(stk_item) - 2 ; i++)
    {
      *stack++ = *stackCover++;
    }
}




static void __InitThread(_pcb* pro,_str stream,unsigned int image_size,unsigned int load_addr)
{/*
  //unsigned int orgflPage = NOWT->init_argv[0];
  //_pcb* orgpro = NOWT->pPro;
  //NOWT->pPro = pro;
  //NOWT->init_argv[0] = pro->flPage;
  SetFPBaseAddr(pro->flPage);
  //Set First Page Base Address Okay	
  //ReadStreamEx(stream,load_addr,image_size);
  //Copy Okay
  //NOWT->init_argv[0] = orgflPage;
  NOWT->pPro = pro;
  SetFPBaseAddr(orgflPage);
 */
}

static _pcb* ExcuteFile(char* filepath,unsigned int* argvs,unsigned int argns)
{


	
}

static unsigned int* ProcessPageFork(_pcb* pro,_pcb* orgpro)
{//copy-on-write

}

static _tcb* ProcessFork(_tcb* applicance)
{//no copy-on-write, too much pressure on the kernel memory
  //not finished
  _pcb* newpcb = (_pcb*)_KHEAPAPPLY(sizeof(_pcb));
  _Memcpy(applicance->pPro,newpcb,sizeof(_pcb));
	
}



